﻿using JavaDevToys.Rcl.Models;
using JavaDevToys.Rcl.Utils;
using Scriban.Runtime;
using Scriban;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Masa.Blazor.Docs;

namespace JavaDevToys.Rcl.Service.Impl
{
    public class ExInterfaceCodeService : IExInterfaceCodeService
    {
        private static readonly Type docClassType = typeof(DocClass);
        private static readonly PropertyInfo[] docClassProperties = docClassType.GetProperties();
        public string CreateCode(string className, string nameSpeace, string code, string projectType, List<string> docTitles, Dictionary<string, string> typeMap)
        {
            var docClasses = CreateDocClass(code, docTitles);
            docClasses = MappingType(docClasses, typeMap);
            return CreateCodeWithTemp(projectType, className, nameSpeace, docClasses);
        }

        private List<DocClass> CreateDocClass(string code, List<string> docTitles)
        {
            var cols = code.Split('\n');
            List<DocClass> docClasses = new();
            foreach (var col in cols)
            {
                if (string.IsNullOrWhiteSpace(col))
                    continue;
                DocClass docClass = new();
                var columns = col.Split('\t');
                for (int i = 0; i < columns.Length; i++)
                {
                    if (i >= docTitles.Count)
                        continue;
                    var parperName = docTitles[i];
                    var filed = docClassProperties.FirstOrDefault(f => f.GetCustomAttribute<DescriptionAttribute>()?.Description == parperName);
                    if (filed != null)
                    {
                        filed.SetValue(docClass, columns[i]);
                    }
                }
                if(string.IsNullOrWhiteSpace(docClass.Code))
                    continue;
                docClasses.Add(docClass);
            }
            return docClasses;
        }

        private List<DocClass> MappingType(List<DocClass> docClasses, Dictionary<string, string> typeMap)
        {
            foreach (var item in docClasses)
            {
                if (string.IsNullOrWhiteSpace(item.Type))
                {
                    item.Type = "{NotFundType}";
                    continue;
                }
                if(!typeMap.TryGetValue(item.Type, out var type))
                {
                    throw new Exception($"类型【{item.Type}】缺少映射!");
                }
                var typeFiled = type;
                typeFiled = typeFiled.Replace("&lt;", "<").Replace("&gt;", ">");
                item.Type = typeFiled;
            }
            return docClasses;
        }

        private string CreateCodeWithTemp(string projectType,string className,string nameSpeace, List<DocClass> docClasses)
        {
            var context = new JavaTempData()
            {
                package_name = nameSpeace,
                class_name = className,
                parameters = docClasses.Select(s => new JavaTempData_Parameter()
                {
                    data_type = s.Type,
                    description = s.Name+(string.IsNullOrWhiteSpace(s.Remark)?"":$"({s.Remark})"),
                    parameter_name = s.Code,
                    required = false,
                }).ToList(),
            };
            string templateName = string.Empty;
            if (projectType == "Java")
            {
                templateName = "TemplateJavaClass.scriban";
            }
            if(projectType == "CSharp")
            {
                templateName = "TemplateCSharpClass.scriban";
            }
            return CreateCodeWithTemp(templateName, context);
        }

        private string CreateCodeWithTemp(string templateName, object data)
        {
            var templatePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ExInterfaceTemp", templateName);
            var templateContent = File.ReadAllText(templatePath);
            var template = Template.Parse(templateContent);
            // 创建 TemplateContext 并启用内置函数
            var context = new TemplateContext();
            var scriptObject = new ScriptObject();
            scriptObject.Import(data); // 将数据导入到模板
            context.PushGlobal(scriptObject);

            // 启用内置函数
            scriptObject.Import(typeof(JavaCodeHelper));

            var result = template.Render(context);
            return result;
        }
    }
}
